# Copyright (C) 2006  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

#
# For more information visit http://carrierclass.net/
#

use strict;
use warnings;

package CCNCore::Provision::ChangeSet;
use base qw(CCN::Provision::Base);

# When a new changeset record or changesetvalues record is created, it is 
# propagated to all the servers that need to know about it.
# (This probably looks like a SUBSCRIBE/NOTIFY kind of activity.)
# The changeset is then added in the local database (offline, SQLite) on that
# server.

# Subsequentially, the changeset may be either (a) applied or (b) canceled.
# In either cases, all servers that received the changeset are notified.
# In turn, locally, they must be able to find which modules are interested
# by the changeset.
# Process:
# (1) Run either ChangeSet::Tools::apply_changeset or ChangeSet::Tools::cancel_changeset
# (2) Run ChangeSet::Tools::run_changeset

=pod
    register_on_table
        Allows a module to register its interest for changes about a particular table.
=cut

our %on_table;

sub register_on_table
{
    my $object = shift;
    my $table  = shift;
    
    push @{$on_table{$table}}, ref($oject);
}

=pod
    register_on_table
        Allows a module to register its interest for changes about a particular column.
=cut

our %on_column;

sub register_on_column
{
    my $object = shift;
    my $table  = shift;
    my $column = shift;

    push @{$on_column{$table,$column}}, ref($oject);
}

=pod
    apply_table
        Is called from within the spool event to actually apply the modifications
        once the proper ChangeSet::Tools::apply_changeset or ChangeSet::Tools::cancel_changeset
        has been ran.
=cut

sub on_table
{
    my $self = shift;
    my $table = shift;
    for my $s (@{$on_table{$table}})
    {
        my $c = $self->_new_class($s);
        $c->on_table($table,@_);
    }
}

sub on_column
{
    my $self = shift;
    my $table = shift;
    my $column = shift;
    for my $s (@{$on_column{$table,$column}})
    {
        my $c = $self->_new_class($s);
        $c->on_column($table,$column,@_);
    }
}

sub _new_class
{
    my $self = shift;
    my $s = shift;
    my $p = $self->p;
    my $c;
    eval "use $s; \$c = new $s(\$p);";
    # Eval failed
    $self->die("Module $s: $@") if $@;
    $self->die("Module $s: creation failed") unless defined $c;
    return $c;
}

1;